﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using Common;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace ImageProcessPlugins
{
    public class TransformPlugins : IProcessorPlugin
    {
        private ImageProcessApp app;

        public void RegisterMenu(IMenuRegistry registry)
        {
            registry.RegisterMenuItem("&Transform", "&Horizontal Flip", "HorizontalFlip", Keys.None, this);
            registry.RegisterMenuItem("&Transform", "&Vertical Flip", "VerticalFlip", Keys.None, this);
            registry.RegisterMenuItem("&Transform", "Rotate 90 degree &clockwise", "Rotate90Degree", Keys.Control|Keys.Right, this);
            registry.RegisterMenuItem("&Transform", "Rotate 90 degree coun&ter-clockwise", "Rotate90DegreeCounter", Keys.Control|Keys.Left, this);
            registry.RegisterMenuItem("&Transform", "Rotate &Arbitary...", "RotateArbitary", Keys.None, this);
            registry.RegisterMenuItem("&Transform", "&Resize...", "Resize", Keys.Control|Keys.H, this);
            //registry.RegisterMenuItem("&Transform", "&Scissor...", "Scissor", Keys.None, this);
            registry.RegisterMenuItem("&Transform", "&Scissor...", "HYScissor", Keys.None, this);
            registry.RegisterMenuItem("&Transform", "Image &Walk...", "ImageWalk", Keys.None, this);
        }

        public void ProcessCommand(string command, Document doc)
        {
            switch (command)
            {
                case "HorizontalFlip":
                    HorizontalFlip(doc);
                    break;
                case "VerticalFlip":
                    VerticalFlip(doc);
                    break;
                case "Rotate90Degree":
                    Rotate90Degree(doc);
                    break;
                case "Rotate90DegreeCounter":
                    Rotate90DegreeCounter(doc);
                    break;
                case "RotateArbitary":
                    RotateArbitary(doc);
                    break;
                case "Resize":
                    Resize(doc);
                    break;
                case "Scissor":
                    Scissor(doc);
                    break;
                case "HYScissor":
                    HY_Scissor(doc);
                    break;
                case "ImageWalk":
                    ImageWalk(doc);
                    break;
            }
        }

        private void ImageWalk(Document doc)
        {
            ImageWalkForm form = new ImageWalkForm(doc);
            if (form.ShowDialog() == DialogResult.OK)
            {
                app.ImageView.ViewMode = app.ImageView.ViewMode;
                app.ImageView.Refresh();
            };
        }

        private void HY_Scissor(Document doc)
        {
            HY_ScissorForm form = new HY_ScissorForm();
            form.SetBitmap(doc.GetBitmap());
            if (form.ShowDialog() == DialogResult.OK)
            {
                Rectangle rect = form.GetImageRectangle();
                if (rect.Height > 0 && rect.Width > 0)
                {
                    Bitmap nBit = new Bitmap(rect.Width, rect.Height);
                    Graphics g = Graphics.FromImage(nBit);
                    g.DrawImage(doc.GetBitmap(), new Rectangle(0, 0, rect.Width, rect.Height), rect, GraphicsUnit.Pixel);
                    doc.SetBitmap(nBit);
                    app.ImageView.ViewMode = app.ImageView.ViewMode;
                    app.ImageView.Refresh();
                }
            };
        }

        private void Resize(Document doc)
        {
            ResizeForm form = new ResizeForm();
            form.OriHeight = doc.GetBitmap().Height;
            form.OriWidth = doc.GetBitmap().Width;
            if (form.ShowDialog() == DialogResult.OK)
            {
                Bitmap bmp = new Bitmap(form.NewWidth, form.NewHeight);
                Graphics g = Graphics.FromImage(bmp);
                g.DrawImage(doc.GetBitmap(), 0, 0, form.NewWidth, form.NewHeight);
                doc.SetBitmap(bmp);
                app.ImageView.ViewMode = ViewMode.OriginalSize;
            }
        }

        public void Load(ImageProcessApp App)
        {
            app = App;
        }

        public void Unload()
        {
        }

        private void VerticalFlip(Document doc)
        {
            Bitmap bitmap = doc.GetBitmap();
            Bitmap result = VerticalFlip(bitmap);
            doc.SetBitmap(result);
            app.ImageView.Refresh();
        }

        public static Bitmap VerticalFlip(Bitmap bitmap)
        {
            Bitmap result = new Bitmap(bitmap.Width, bitmap.Height);
            Graphics g = Graphics.FromImage(result);
            g.Transform = new Matrix(new Rectangle(0, 0, bitmap.Width, bitmap.Height), new PointF[3] { new PointF(0, bitmap.Height), new PointF(bitmap.Width, bitmap.Height), new PointF(0, 0) });
            g.DrawImage(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height), 0, 0, bitmap.Width, bitmap.Height, GraphicsUnit.Pixel);
            return result;
        }

        private void HorizontalFlip(Document doc)
        {
            Bitmap bmp = doc.GetBitmap();
            Bitmap rs = new Bitmap(bmp.Width, bmp.Height);
            Graphics g = Graphics.FromImage(rs);
            g.Transform = new Matrix(-1.0f, 0.0f, 0.0f, 1.0f, bmp.Width, 0.0f);
            g.DrawImage(bmp, 0, 0);
            doc.SetBitmap(rs);
            app.ImageView.Refresh();
        }

        private void Rotate90Degree(Document doc)
        {
            Bitmap bitmap = doc.GetBitmap();
            Bitmap result = new Bitmap(bitmap.Height, bitmap.Width);
            Graphics g = Graphics.FromImage(result);
            g.Transform = new Matrix(0.0f, 1.0f, -1.0f, 0.0f, bitmap.Height, 0.0f);
            g.DrawImage(bitmap, 0, 0);
            doc.SetBitmap(result);
            app.ImageView.ViewMode = ViewMode.BestFit;
        }

        private void Rotate90DegreeCounter(Document doc)
        {
            Bitmap bitmap = doc.GetBitmap();
            Bitmap result = new Bitmap(bitmap.Height, bitmap.Width);
            Graphics g = Graphics.FromImage(result);
            g.Transform = new Matrix(0.0f, -1.0f, 1.0f, 0.0f, 0, bitmap.Width);
            g.DrawImage(bitmap, 0, 0);
            doc.SetBitmap(result);
            app.ImageView.ViewMode = ViewMode.BestFit;
        }

        private void RotateArbitary(Document doc)
        {
            using (RotateInputForm form = new RotateInputForm())
            {
                form.SetCurrentDoc(doc);
                form.SetImageProcessApp(app);
                DialogResult dialogResult = form.ShowDialog();
            }
        }

        private Point RotatePoint(Point point, float angle)
        {
            int x = (int)(point.X * Math.Cos(angle) - point.Y * Math.Sin(angle));
            int y = (int)(point.X * Math.Sin(angle) + point.Y * Math.Cos(angle));
            return new Point(x, y);
        }

        private void Scissor(Document doc)
        {
            using (ScissorForm form = new ScissorForm())
            {
                form.SetCurrentDoc(doc);
                form.ShowDialog();
            }
        }
    }
}
